package com.flame.shapeville.bean;

import com.flame.shapeville.enums.TaskStyle;
import com.flame.shapeville.util.YamlIgnore;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;

/**
 * Represents a learning task associated with a course and a user.
 * <p>
 * Contains metadata, exercises, scoring info, and completion status.
 *
 * @author Flame Dev Team
 * @version 1.0
 * @since 2025-05-01
 */
@Data
@NoArgsConstructor
public class Task {
    /**
     * Unique ID of the task.
     */
    private String id;

    /**
     * Style or type of the task.
     */
    private TaskStyle style;

    /**
     * Name of the task.
     */
    private String name;

    /**
     * ID of the user who owns this task.
     */
    private String userId;

    /**
     * ID of the course this task belongs to.
     */
    private String courseId;

    /**
     * Count of basic-level exercises.
     */
    private int basicCount;

    /**
     * Count of advanced-level exercises.
     */
    private int advancedCount;

    /**
     * List of all exercises in this task.
     * This field is ignored during YAML serialization.
     */
    @YamlIgnore
    private List<Exercise> exercises;

    /**
     * Total score obtained in basic exercises.
     */
    @YamlIgnore
    private int basicScore;

    /**
     * Count of correctly completed basic exercises.
     */
    @YamlIgnore
    private int basicCorrectCount;

    /**
     * Whether all basic exercises are completed.
     */
    @YamlIgnore
    @Getter
    private boolean basicCompleted;

    /**
     * Total score obtained in advanced exercises.
     */
    @YamlIgnore
    private int advancedScore;

    /**
     * Count of correctly completed advanced exercises.
     */
    @YamlIgnore
    private int advancedCorrectCount;

    /**
     * Whether all advanced exercises are completed.
     */
    @YamlIgnore
    @Getter
    private boolean advancedCompleted;

    /**
     * Total score across all exercises.
     */
    @YamlIgnore
    private int totalScore;

    /**
     * Total number of completed exercises.
     */
    @YamlIgnore
    private int completeCount;

    /**
     * Constructs a new task based on the given style.
     *
     * @param id        the unique ID of the task
     * @param userId    the ID of the associated user
     * @param courseId  the ID of the associated course
     * @param style     the type/style of the task
     */
    public Task(String id, String userId, String courseId, TaskStyle style) {
        this.id = id;
        this.userId = userId;
        this.courseId = courseId;
        this.style = style;
        switch (style) {
            case TASK1:
                this.name = "Identification of Shapes";
                this.basicCount = 4;
                this.advancedCount = 4;
                break;
            case TASK2:
                this.name = "Identification of Angle Types";
                this.basicCount = 4;
                this.advancedCount = 0;
                break;
            case TASK3:
                this.name = "Area Calculation of Shapes";
                this.basicCount = 4;
                this.advancedCount = 0;
                break;
            case TASK4:
                this.name = "Area and Circumference Calculation of Circle";
                this.basicCount = 4;
                this.advancedCount = 0;
                break;
            case BONUS1:
                this.name = "Compound Shapes Area Calculation";
                this.basicCount = 0;
                this.advancedCount = 6;
                break;
            case BONUS2:
                this.name = "Sector of a Circuit Area";
                this.basicCount = 0;
                this.advancedCount = 8;
                break;
        }
    }

    /**
     * Sets the list of exercises for this task and recalculates related scores and statuses.
     *
     * @param exercises the list of exercises to associate with this task
     */
    public void setExercises(List<Exercise> exercises) {
        this.exercises = exercises;
        this.basicScore = 0;
        this.advancedScore = 0;
        this.basicCompleted = basicCount != 0;
        this.advancedCompleted = advancedCount != 0;
        for (Exercise exercise : exercises) {
            if (!exercise.getAdvanced()) {
                basicScore += exercise.getScore();
                if (exercise.getCompleted() && exercise.getScore() > 0) {
                    basicCorrectCount++;
                }
            } else {
                advancedScore += exercise.getScore();
                if (exercise.getCompleted() && exercise.getScore() > 0) {
                    advancedCorrectCount++;
                }
            }
            totalScore += exercise.getScore();
            if (exercise.getCompleted()) {
                completeCount++;
            }
            if (!exercise.getCompleted()) {
                if (exercise.getAdvanced()) {
                    advancedCompleted = false;
                } else {
                    basicCompleted = false;
                }
            }
        }
    }

    /**
     * Checks whether this task is fully completed.
     * A task is considered completed when all its exercises have been finished.
     *
     * @return true if all exercises are completed; false otherwise
     */
    public boolean isCompleted() {
        return completeCount == basicCount + advancedCount;
    }
}
